﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Masood.Utilities.EmailTemplates.Items;

namespace Masood.Utilities.EmailTemplates.Manager
{
    public abstract class AbstractTemplateManager
    {
        /// <summary>
        /// This method needs to be implemented by concrete classes.
        /// </summary>
        /// <param name="templateId">Unique template id maintained by the systems</param>
        /// <returns>An object of EmailTemplate class</returns>
        public abstract EmailTemplate GetTemplate(string templateId);

        /// <summary>
        /// Call this method to apply email template on given item.
        /// </summary>
        /// <param name="templateId">Unique template id maintained by the system</param>
        /// <param name="anItem">An item of IItem interface. For instance an order item etc</param>
        /// <returns>Applied templates on Email object</returns>
        public Email ApplyTemplate(string templateId, IItem anItem)
        {
            EmailTemplate template = GetTemplate(templateId);
            Email email = new Email();
            email.Subject = template.Subject;
            email.Body = template.Body;

            BeforeApplyingTemplateOnSubject(template, ref email, anItem);
            ApplyTemplateOnSubject(template, ref email, anItem);
            AfterApplyingTemplateOnSubject(template, ref email, anItem);

            BeforeApplyingTemplateOnBody(template, ref email, anItem);
            ApplyTemplateOnBody(template, ref email, anItem);
            AfterApplyingTemplateOnBody(template, ref email, anItem);

            return email;
        }

        /// <summary>
        /// This method gets called before applying the template on subject of email. if you want to implement then override otherwise you don't need to do anything
        /// </summary>
        /// <param name="template">Actual template will be provided by the framework</param>
        /// <param name="email">This is the actual email, which contains the applied values. It will be supplied by the framework.</param>
        /// <param name="anItem">This is the item where you want to read values from. It will be supplied by the framework.</param>
        public virtual void BeforeApplyingTemplateOnSubject(EmailTemplate template, ref Email email, IItem anItem)
        {
        }

        private void ApplyTemplateOnSubject(EmailTemplate template, ref Email email, IItem anItem)
        {
            string subject = email.Subject;
            string fieldNameInTemplate = string.Empty;
            string correspondingFieldValue = string.Empty;

            foreach (string fieldName in anItem.FieldAndValues.Keys)
            {
                fieldNameInTemplate = string.Format("[{0}]", fieldName);
                if (anItem.FieldAndValues.ContainsKey(fieldName))
                {
                    correspondingFieldValue = anItem.FieldAndValues[fieldName];
                    subject = subject.Replace(fieldNameInTemplate, correspondingFieldValue);
                }
            }

            email.Subject = subject;            
        }

        /// <summary>
        /// This method gets called after applying the template on subject of email. If you want to implement, override it otherwise leave it.
        /// </summary>
        /// <param name="template">Actual template will be provided by the framework</param>
        /// <param name="email">This is the actual email, which contains the applied values. It will be supplied by the framework.</param>
        /// <param name="anItem">This is the item where you want to read values from. It will be supplied by the framework.</param>
        public virtual void AfterApplyingTemplateOnSubject(EmailTemplate template, ref Email email, IItem anItem)
        {
        }

        /// <summary>
        /// This method gets called after applying the template on body of email. If you don't want to do anything, just leave the implementation empty but DO NOT throw exception.
        /// </summary>
        /// <param name="template">Actual template will be provided by the framework</param>
        /// <param name="email">This is the actual email, which contains the applied values. It will be supplied by the framework.</param>
        /// <param name="anItem">This is the item where you want to read values from. It will be supplied by the framework.</param>
        public virtual void BeforeApplyingTemplateOnBody(EmailTemplate template, ref Email email, IItem anItem)
        {
        }

        private void ApplyTemplateOnBody(EmailTemplate template, ref Email email, IItem anItem)
        {
            string body = email.Body;
            string fieldNameInTemplate = string.Empty;
            string correspondingFieldValue = string.Empty;

            foreach (string fieldName in anItem.FieldAndValues.Keys)
            {
                fieldNameInTemplate = string.Format("[{0}]", fieldName);
                if (anItem.FieldAndValues.ContainsKey(fieldName))
                {
                    correspondingFieldValue = anItem.FieldAndValues[fieldName];
                    body = body.Replace(fieldNameInTemplate, correspondingFieldValue);
                }
            }

            email.Body = body;
        }

        /// <summary>
        /// This method gets called after applying the template on body of email. If you don't want to do anything, just leave the implementation empty but DO NOT throw exception.
        /// </summary>
        /// <param name="template">Actual template will be provided by the framework</param>
        /// <param name="email">This is the actual email, which contains the applied values. It will be supplied by the framework.</param>
        /// <param name="anItem">This is the item where you want to read values from. It will be supplied by the framework.</param>
        public virtual void AfterApplyingTemplateOnBody(EmailTemplate template, ref Email email, IItem anItem)
        {
        }

    }
}
